﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Charts;
using System.Runtime.Serialization.Json;
using System.Threading;
using System.Globalization;
using System.IO;

namespace OpenGovernment
{
    public partial class DataViz : PhoneApplicationPage
    {
        HttpWebRequest request;
        string sort;
        PieChart pie;
        SolidColorBrush brush;
        public DataViz()
        {
            InitializeComponent();
            Loaded += delegate
            {
                pie = new PieChart()
                {
                    Center = new Point(240.0, 190.0),
                    Radius = 190.0,
                    Stroke = new SolidColorBrush(Colors.LightGray),
                    StrokeThickness = 2.0,
                    FontSize = 10.0,
                    LabelStroke = new SolidColorBrush(Colors.Black),
                    Segments = new PieSegmentList()
                };
                LayoutRoot.Children.Add(pie);
                brush = new SolidColorBrush(Colors.Cyan);
            };
        }
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            var to = NavigationContext.QueryString["to"];
            var from = NavigationContext.QueryString["from"];
            sort = NavigationContext.QueryString["sort"];
            var filt = Convert.ToBoolean(NavigationContext.QueryString["filter"]);
            var filter = "";
            if (filt)
            {
              //  filter = "&signer=1;4583;4584;4582;9485;9488;9590;22639;24879;22402;3386;3387;118;119;122;125;14;18892;18895;19067;22869;21155;19115;19204;20261;20467;20468;2707;2709;2715;2723;2725;3210;2734;2730;871;872;876;879;23874;24049;24048;4604;9590;9579;236;18;19;24;63;3851;14000;101;256;257;270";
                filter = "&signer=19204;61;118;22950;18895;256;18894;22905;872;3210;4411;4557;4558;4559;4560;4561;4562;4563;10081;2399;3860;3863;3865";
            }
            request = (HttpWebRequest)WebRequest.Create("http://opendata.diavgeia.gov.gr/api/decisions?type=27&datefrom=" + from +"&dateto=" + to + filter +  "&output=json");
            request.BeginGetResponse(Callback, null);
        }
        private void Callback(IAsyncResult result)
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo("el-GR");
            Stream stream;
            try
            {
                stream = request.EndGetResponse(result).GetResponseStream();
            }
            catch (WebException) { Dispatcher.BeginInvoke(() => bar.IsIndeterminate = false); return; }
            var decisions = ((RootObject)new DataContractJsonSerializer(typeof(RootObject)).ReadObject(stream)).model.decisions.Where(y => y.metadata.extraFields != null);
            var expenses = decisions.Select(y => new Expense() { orgid = y.metadata.organizationId, signerid = y.metadata.signerId, amount = String.IsNullOrEmpty(y.metadata.extraFields.extraField.Single(x => x.name == "poso_dapanis").value.Replace(".", "")) ? 0 : Convert.ToDouble(y.metadata.extraFields.extraField.Single(x => x.name == "poso_dapanis").value.Replace(".", "")) }).ToList();
            if (sort == "org")
            {
                Process(expenses, true);
            }
            if (sort == "signer")
            {
                if (App.signersReady)
                {
                    Process(expenses, false);
                }
                else
                {
                    App.SignersReady += delegate
                    {
                        Process(expenses, false);
                    };
                }
            }
        }
        private void Process(List<Expense> expenses, bool org)
        {
            var total = 0.0;
            var segments = new List<Segment>();
            foreach (var expense in expenses)
            {
                var name = org ? MainPage.data.getOrgFromId(expense.orgid) : App.GetSignerFromId(expense.signerid);
                total += expense.amount;
                try
                {
                    segments.Single(y => y.name == name).amount += expense.amount;
                }
                catch (InvalidOperationException)
                {
                    segments.Add(new Segment { name = name, amount = expense.amount });
                }
            }
            Display(segments, total);
        }
        private void Display(List<Segment> segments, double total)
        {
            var slices = new PieSegmentList();
            var anon = new [] {new { text = "", fill = brush }}.ToList().ToEmpty();
            foreach (var segment in segments)
            {
                var p = segment.amount / total * 100;
                var name = segment.name;
                Dispatcher.BeginInvoke(() =>
                {
                    NextBrush();
                    slices.Add(new PieSegment() { Percentage = p, Foreground = brush });
                    anon.Add(new {text = name, fill = brush });
                });
            }
            Dispatcher.BeginInvoke(() =>
            {
                pie.Segments = slices;
                list.ItemsSource = anon;
                bar.IsIndeterminate = false;
            });
        }
        public class Segment
        {
            public string name;
            public double amount;
        }
        public class Expense
        {
            public int orgid { get; set; }
            public int signerid { get; set; }
            public double amount { get; set; }
        }

        int mLastColor = 0;
        Color[] mColors = {Colors.Cyan, Colors.Magenta, Colors.DarkGray, Colors.Green, Colors.Orange, Colors.Purple, Colors.Black, Colors.Gray, Colors.Blue, Colors.Brown, Colors.LightGray, Colors.Red, Colors.White, Colors.Yellow};
        Random random = new Random();
        private Color GetNextColor()
        {
            if (mLastColor >= mColors.Length)
            {
                return Color.FromArgb(255, (byte)random.Next(255), (byte)random.Next(255), (byte)random.Next(255));
            }
            else
            {
                return mColors[mLastColor++];
            }
        }
        public void NextBrush()
        {
            brush = new SolidColorBrush(GetNextColor());
        }
    }
}